
#include "software_i2c.h"
#include <stdint.h>
#include <stdbool.h>
#include "py32f0xx_hal.h"
#include "APDS9960.h" 

#if HARDWARE_DEV1
#define  _SDA1_pin    2   //PB2
#define  _SCL1_pin    3   //PB3

#define  _SDA2_pin    0   //PB0
#define  _SCL2_pin    3   //PB3

#define  _SDA3_pin    4   //PB4
#define  _SCL3_pin    3   //PB3

#define  _SDA4_pin    5   //PB5
#define  _SCL4_pin    3   //PB3

#endif



#if HARDWARE_DEV2
#define  _SDA1_pin    2   //PB2
#define  _SCL1_pin    3   //PB3

#define  _SDA2_pin    0   //PB0
#define  _SCL2_pin    3   //PB3

#define  _SDA3_pin    4   //PB4
#define  _SCL3_pin    3   //PB3

#define  _SDA4_pin    5   //PB5
#define  _SCL4_pin    3   //PB3


#endif


/// ??????? I2C ?????????
static I2C_Config i2c_buses[I2C_BUS_COUNT];


void I2C_Delay(void){

	
	 volatile int i;
    for(i = 0; i < 10; i++) { // ??????????????
        __NOP();
    }
	//HAL_Delay(1);
	//for (volatile int i = 0; i < 2; i++); // ???????????? I2C ????????

}

/*********************************************************************************
* function   :   Factory_Register_CallBack     
* Description :  ????????????????????????
* Input       :  
* Output      :  
* Author      :                    Data : 2024 07.10
**********************************************************************************/	
void Set_SDA_1(uint8_t pin, bool level){
	
	#if HARDWARE_DEV1
	if(pin == _SDA1_pin){
		
		
						
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
	#endif
	
	
		#if HARDWARE_DEV2
	if(pin == _SDA1_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
	#endif
			
}
	

void Set_SCL_1(uint8_t pin, bool level){
	
		#if HARDWARE_DEV1
		if(pin == _SCL1_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
	
	
			#if HARDWARE_DEV2
		if(pin == _SCL1_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
}

bool Read_SDA_1(uint8_t pin){
		
		#if HARDWARE_DEV1
		if(pin == _SDA1_pin){
			
			
			// GPIO_InitTypeDef  gpio_init;
			// gpio_init.Pin = GPIO_PIN_1;
			// gpio_init.Mode = GPIO_MODE_INPUT;            /* Push-pull output */
			// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
			// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
			// HAL_GPIO_Init(GPIOB, &gpio_init);
				
			return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		}
		#endif
	
	
	#if HARDWARE_DEV2
		if(pin == _SDA1_pin){
				
			return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		}
		#endif
	
}


bool CONFIG_DIR_SDA_1(uint8_t pin,bool in_or_out){
		
		#if HARDWARE_DEV1
		if(pin == _SDA1_pin){
			
			if(in_or_out){

				// HAL_GPIO_DeInit(GPIOB,GPIO_PIN_1);
				// GPIO_InitTypeDef  gpio_init;
				// gpio_init.Pin = GPIO_PIN_1;
				// gpio_init.Mode = GPIO_MODE_INPUT;            /* Push-pull output */
				// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
				// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
				// HAL_GPIO_Init(GPIOB, &gpio_init);
			}else
			{
				
				// HAL_GPIO_DeInit(GPIOB,GPIO_PIN_1);
				// GPIO_InitTypeDef  gpio_init;
				// gpio_init.Pin = GPIO_PIN_1;
				// gpio_init.Mode = GPIO_MODE_OUTPUT_OD;            /* Push-pull output */
				// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
				// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
				// HAL_GPIO_Init(GPIOB, &gpio_init);
			}
				
			//return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		}
		#endif
}



/*********************************************************************************
* function   :     
* Description :  
* Input       :  
* Output      :  
* Author      :                    Data : 2024 07.10
**********************************************************************************/	
void Set_SDA_2(uint8_t pin, bool level){
	
	#if HARDWARE_DEV1	
	if(pin == _SDA2_pin){
		
		
		// GPIO_InitTypeDef  gpio_init;
		// 	gpio_init.Pin = GPIO_PIN_0;
		// 	gpio_init.Mode = GPIO_MODE_OUTPUT_OD;            /* Push-pull output */
		// 	gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
		// 	gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
		// 	HAL_GPIO_Init(GPIOB, &gpio_init);
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
	#endif
	
		#if HARDWARE_DEV2	
	if(pin == _SDA2_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
	#endif
}

void Set_SCL_2(uint8_t pin, bool level){
	
		#if HARDWARE_DEV1
		if(pin == _SCL2_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
	
	
			#if HARDWARE_DEV2
		if(pin == _SCL2_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
}

bool Read_SDA_2(uint8_t pin){
		
	#if HARDWARE_DEV1
		if(pin == _SDA2_pin){
			
			
			// GPIO_InitTypeDef  gpio_init;
			// gpio_init.Pin = GPIO_PIN_0;
			// gpio_init.Mode = GPIO_MODE_INPUT;            /* Push-pull output */
			// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
			// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
			// HAL_GPIO_Init(GPIOB, &gpio_init);
				
				
			return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
		}
	#endif
	
	
	#if HARDWARE_DEV2
		if(pin == _SDA2_pin){
				
			return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
		}
	#endif
}



bool CONFIG_DIR_SDA_2(uint8_t pin,bool in_or_out){
		
		#if HARDWARE_DEV1
		if(pin == _SDA2_pin){
			
			if(in_or_out){


				
				// HAL_GPIO_DeInit(GPIOB,GPIO_PIN_0);
				// GPIO_InitTypeDef  gpio_init;
				// gpio_init.Pin = GPIO_PIN_0;
				// gpio_init.Mode = GPIO_MODE_INPUT;            /* Push-pull output */
				// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
				// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
				// HAL_GPIO_Init(GPIOB, &gpio_init);
			}else
			{
				// HAL_GPIO_DeInit(GPIOB,GPIO_PIN_0);
				// GPIO_InitTypeDef  gpio_init;
				// gpio_init.Pin = GPIO_PIN_0;
				// gpio_init.Mode = GPIO_MODE_OUTPUT_OD;            /* Push-pull output */
				// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
				// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
				// HAL_GPIO_Init(GPIOB, &gpio_init);
			}
				
			//return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		}
		#endif
}



/*********************************************************************************
* function   :   Factory_Register_CallBack     
* Description :  ????????????????????????
* Input       :  
* Output      :  
* Author      :                    Data : 2024 07.10
**********************************************************************************/	
void Set_SDA_3(uint8_t pin, bool level){
	
		#if HARDWARE_DEV1
	if(pin == _SDA3_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
	#endif
	
		#if HARDWARE_DEV2
	if(pin == _SDA3_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
	#endif
}

void Set_SCL_3(uint8_t pin, bool level){
		#if HARDWARE_DEV1
		if(pin == _SCL3_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
	
			#if HARDWARE_DEV2
		if(pin == _SCL3_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
}

bool Read_SDA_3(uint8_t pin){
	
		#if HARDWARE_DEV1
			if(pin == _SDA3_pin){
				
			return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_4);
		}
			#endif
	
		#if HARDWARE_DEV2
			if(pin == _SDA3_pin){
				
			return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_4);
		}
			#endif
}



bool CONFIG_DIR_SDA_3(uint8_t pin,bool in_or_out){
		
		#if HARDWARE_DEV1
		if(pin == _SDA3_pin){
			
			if(in_or_out){

				// HAL_GPIO_DeInit(GPIOB,GPIO_PIN_4);
				// GPIO_InitTypeDef  gpio_init;
				// gpio_init.Pin = GPIO_PIN_4;
				// gpio_init.Mode = GPIO_MODE_INPUT;            /* Push-pull output */
				// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
				// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
				// HAL_GPIO_Init(GPIOB, &gpio_init);
			}else
			{
				// HAL_GPIO_DeInit(GPIOB,GPIO_PIN_4);
				// GPIO_InitTypeDef  gpio_init;
				// gpio_init.Pin = GPIO_PIN_4;
				// gpio_init.Mode = GPIO_MODE_OUTPUT_OD;            /* Push-pull output */
				// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
				// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
				// HAL_GPIO_Init(GPIOB, &gpio_init);
			}
				
			//return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		}
		#endif
}



/*********************************************************************************
* function   :   Factory_Register_CallBack     
* Description :  ????????????????????????
* Input       :  
* Output      :  
* Author      :                    Data : 2024 07.10
**********************************************************************************/	
void Set_SDA_4(uint8_t pin, bool level){
	
		#if HARDWARE_DEV1

		if(pin == _SDA4_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
	
	
		#if HARDWARE_DEV2

		if(pin == _SDA4_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
}

void Set_SCL_4(uint8_t pin, bool level){
	
		#if HARDWARE_DEV1
		if(pin == _SCL4_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
	
			#if HARDWARE_DEV2
		if(pin == _SCL4_pin){
				
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,level == true?GPIO_PIN_SET:GPIO_PIN_RESET);
		}
		#endif
}

bool Read_SDA_4(uint8_t pin){
	
	#if HARDWARE_DEV1
		if(pin == _SDA4_pin){
				
			return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_5);
		}
	#endif
	
		#if HARDWARE_DEV2
		if(pin == _SDA4_pin){
				
			return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_5);
		}
	#endif

}



bool CONFIG_DIR_SDA_4(uint8_t pin,bool in_or_out){
		
		#if HARDWARE_DEV1
		if(pin == _SDA4_pin){
			
			if(in_or_out){

				// HAL_GPIO_DeInit(GPIOB,GPIO_PIN_5);
				// GPIO_InitTypeDef  gpio_init;
				// gpio_init.Pin = GPIO_PIN_5;
				// gpio_init.Mode = GPIO_MODE_INPUT;            /* Push-pull output */
				// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
				// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
				// HAL_GPIO_Init(GPIOB, &gpio_init);
			}else
			{
				// HAL_GPIO_DeInit(GPIOB,GPIO_PIN_5);
				// GPIO_InitTypeDef  gpio_init;
				// gpio_init.Pin = GPIO_PIN_5;
				// gpio_init.Mode = GPIO_MODE_OUTPUT_OD;            /* Push-pull output */
				// gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
				// gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
				// HAL_GPIO_Init(GPIOB, &gpio_init);
			}
				
			//return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		}
		#endif
}


  


// ????? I2C ????
void I2C_Init(void) {
    // ???????? I2C ?????????
    // ???? SDA ?? SCL ???????????????????
    i2c_buses[0].SDA_pin = _SDA1_pin;  // SDA ????
    i2c_buses[0].SCL_pin = _SCL1_pin;  // SCL ????
    i2c_buses[0].Set_SDA = Set_SDA_1;  // ???? SDA ????????
    i2c_buses[0].Set_SCL = Set_SCL_1;  // ???? SCL ????????
    i2c_buses[0].Read_SDA = Read_SDA_1;  // ??? SDA ????????

	i2c_buses[0].Config_SDA_IN_Or_OUT = CONFIG_DIR_SDA_1;
    i2c_buses[0].Delay = I2C_Delay;  // ???????

    i2c_buses[1].SDA_pin = _SDA2_pin;
    i2c_buses[1].SCL_pin = _SCL2_pin;
    i2c_buses[1].Set_SDA = Set_SDA_2;
    i2c_buses[1].Set_SCL = Set_SCL_2;
    i2c_buses[1].Read_SDA = Read_SDA_2;
	i2c_buses[1].Config_SDA_IN_Or_OUT = CONFIG_DIR_SDA_2;
    i2c_buses[1].Delay = I2C_Delay;
	
	
	
	i2c_buses[2].SDA_pin = _SDA3_pin;
    i2c_buses[2].SCL_pin = _SCL3_pin;
    i2c_buses[2].Set_SDA = Set_SDA_3;
    i2c_buses[2].Set_SCL = Set_SCL_3;
    i2c_buses[2].Read_SDA = Read_SDA_3;
	i2c_buses[2].Config_SDA_IN_Or_OUT = CONFIG_DIR_SDA_3;
    i2c_buses[2].Delay = I2C_Delay;
	
	
	
	i2c_buses[3].SDA_pin = _SDA4_pin;
    i2c_buses[3].SCL_pin = _SCL4_pin;
    i2c_buses[3].Set_SDA = Set_SDA_4;
    i2c_buses[3].Set_SCL = Set_SCL_4;
    i2c_buses[3].Read_SDA = Read_SDA_4;
	i2c_buses[3].Config_SDA_IN_Or_OUT = CONFIG_DIR_SDA_4;
    i2c_buses[3].Delay = I2C_Delay;
	




	#if HARDWARE_DEV1
	
	
__HAL_RCC_GPIOA_CLK_ENABLE();                          /* Enable GPIOA clock */
__HAL_RCC_GPIOB_CLK_ENABLE();                          /* Enable GPIOB clock */


	// HAL_GPIO_DeInit(GPIOA,GPIO_PIN_1);


	GPIO_InitTypeDef  gpio_init;
	
	//gpio_init.Pin = GPIO_PIN_1;
	//gpio_init.Mode = GPIO_MODE_OUTPUT_OD;            /* Push-pull output */
	//gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
	//gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */  
	//HAL_GPIO_Init(GPIOA, &gpio_init);

  gpio_init.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
  gpio_init.Mode = GPIO_MODE_OUTPUT_OD;            /* Push-pull output */
  gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
  gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
  HAL_GPIO_Init(GPIOB, &gpio_init);
	
	
	
	//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_SET);

	#endif
	
	
	#if HARDWARE_DEV2
	
	
	__HAL_RCC_GPIOB_CLK_ENABLE();                          /* Enable GPIOB clock */
	GPIO_InitTypeDef  gpio_init;

  gpio_init.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
  gpio_init.Mode = GPIO_MODE_OUTPUT_OD;            /* Push-pull output */
  gpio_init.Pull = GPIO_NOPULL;                    /* Enable pull-up */
  gpio_init.Speed = GPIO_SPEED_FREQ_LOW;          /* GPIO speed */ 
	HAL_GPIO_Init(GPIOB, &gpio_init);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_SET);

	#endif


}


//SCL???????SDA??????��???????

/*********************************************************************************
* function   :   I2C_Start    
* Description :  ?????????I2C????????????????????I2C��??
**********************************************************************************/
void I2C_Start(uint8_t bus_id) {
    if (bus_id < I2C_BUS_COUNT) {

		i2c_buses[bus_id].Config_SDA_IN_Or_OUT(i2c_buses[bus_id].SDA_pin,false);

        // SDA??????��???????SCL???????
        i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, true); // ???SDA??
        i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, true); // ???SCL??
        i2c_buses[bus_id].Delay();
        i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, false); // SDA?????????
        i2c_buses[bus_id].Delay();
        i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, false);  // SCL????
        i2c_buses[bus_id].Delay();
    }
}
//SCL???????SDA??????��???????
/*********************************************************************************
* function   :   I2C_Stop    
* Description :  ???????I2C??????????????????I2C��??
**********************************************************************************/
void I2C_Stop(uint8_t bus_id) {
    if (bus_id < I2C_BUS_COUNT) {

		i2c_buses[bus_id].Config_SDA_IN_Or_OUT(i2c_buses[bus_id].SDA_pin,false);
        // ????? SDA ?????
        i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, false);
        i2c_buses[bus_id].Delay();
        
        // ???? SCL
        i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, true);
        i2c_buses[bus_id].Delay();

        // ?? SCL ?????????? SDA ????��?????
        i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, true);
        i2c_buses[bus_id].Delay();
    }
}


/*********************************************************************************
* function   :   I2C_SendByte    
* Description :  ?????????????��????????????
**********************************************************************************/
void I2C_SendByte(uint8_t bus_id, uint8_t data) {
    if (bus_id < I2C_BUS_COUNT) {
        // ??��???????
        //printf("data %02x\r\n", data);
		i2c_buses[bus_id].Config_SDA_IN_Or_OUT(i2c_buses[bus_id].SDA_pin,false);


		#if 0
        for (uint8_t i = 0; i < 8; i++) {
            bool bit = (data & (1 << (7 - i))) ? true : false; // ??????��
            //printf("%d", bit);
            
            i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, bit); // ?? SDA ��??????
            i2c_buses[bus_id].Delay();  // ??????????
            
            i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, true); // SCL ????
            i2c_buses[bus_id].Delay();  // ??????????????
            
            i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, false); // SCL ????
            i2c_buses[bus_id].Delay();  // ??????????
        }
		#else


		for (uint8_t i = 0; i < 8; i++) {
           // bool bit = (data & (1 << (7 - i))) ? true : false; // ??????��
            //printf("%d", bit);
            if(data & 0x80){

				  i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, true); // ?? SDA ��??????
			}else{

				  i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, false); // ?? SDA ��??????
			}


			data<<=1;
          
            i2c_buses[bus_id].Delay();  // ??????????
            
            i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, true); // SCL ????
            i2c_buses[bus_id].Delay();  // ??????????????
            
            i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, false); // SCL ????
            i2c_buses[bus_id].Delay();  // ??????????
        }
		
		#endif
        
        //printf("\r\n");
    }
}


/*********************************************************************************
* function   :   I2C_ReceiveByte    
* Description :  ?????????????��????????????
**********************************************************************************/
uint8_t I2C_ReceiveByte(uint8_t bus_id) {
    uint8_t data = 0;

	uint8_t receive=0;
    if (bus_id < I2C_BUS_COUNT) {

		i2c_buses[bus_id].Config_SDA_IN_Or_OUT(i2c_buses[bus_id].SDA_pin,true);

		#if 0
        for (int i = 7; i >= 0; i--) {
            i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, true); // SCL????
            i2c_buses[bus_id].Delay();
            if (i2c_buses[bus_id].Read_SDA(i2c_buses[bus_id].SDA_pin)) {
                data |= (1 << i); // ???SDA??????????��
            }
            i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, false); // SCL????
            i2c_buses[bus_id].Delay();
        }
		#else
        for (int i = 0; i <8; i++) {
            i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, true); // SCL????
            i2c_buses[bus_id].Delay();
            if (i2c_buses[bus_id].Read_SDA(i2c_buses[bus_id].SDA_pin)) {
                data |= (0x80>>i); // ???SDA??????????��
            }
			i2c_buses[bus_id].Delay();
            i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, false); // SCL????
            i2c_buses[bus_id].Delay();
        }

		

		#endif
    }
    return data;
}

/*********************************************************************************
* function   :   I2C_SendACK    
* Description :  ????ACK???
**********************************************************************************/
void I2C_SendACK(uint8_t bus_id, bool ack) {
    if (bus_id < I2C_BUS_COUNT) {

		i2c_buses[bus_id].Config_SDA_IN_Or_OUT(i2c_buses[bus_id].SDA_pin,false);
        if (ack) {
            // ????ACK??????????SDA
            i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, false);
        } else {
            // ????NACK?????SDA?????????
            i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, true);
        }
        i2c_buses[bus_id].Delay();  // ???SDA??????

        // ????SCL??????ACK/NACK
        i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, true);
        i2c_buses[bus_id].Delay();

        // ????SCL??????ACK/NACK???
        i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, false);
        i2c_buses[bus_id].Delay();
    }
}


/*********************************************************************************
* function   :   I2C_ReadACK    
* Description :  ???ACK???
**********************************************************************************/
bool I2C_ReadACK(uint8_t bus_id) {
    bool ack = false;
    if (bus_id < I2C_BUS_COUNT) {
        // SDA ??????????? ACK

		i2c_buses[bus_id].Config_SDA_IN_Or_OUT(i2c_buses[bus_id].SDA_pin,true);
        i2c_buses[bus_id].Set_SDA(i2c_buses[bus_id].SDA_pin, true); // SDA ????
		i2c_buses[bus_id].Delay();  // ??????????????
        i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, true);  // SCL ????
        i2c_buses[bus_id].Delay();  // ??????????????

        // ?? SCL ?????? SDA???��? ACK
        ack = !i2c_buses[bus_id].Read_SDA(i2c_buses[bus_id].SDA_pin); // ??? SDA ??
        i2c_buses[bus_id].Delay();  // ??????????????
        // SCL ?????????????????
        i2c_buses[bus_id].Set_SCL(i2c_buses[bus_id].SCL_pin, false); // SCL ????
		i2c_buses[bus_id].Delay();  // ??????????????
    }
    return ack;
}


/*********************************************************************************
* function   :   I2C_Write    
* Description :  I2C��??????????????�???????????????????
**********************************************************************************/
bool I2C_Write(uint8_t bus_id, uint8_t device_addr, uint8_t reg_addr, uint8_t *data, uint8_t length) {
    if (bus_id >= I2C_BUS_COUNT || data == NULL || length == 0) {
        return false;
    }

    I2C_Start(bus_id);
    //if (!I2C_ReadACK(bus_id)) return false;

    I2C_SendByte(bus_id, (device_addr << 1) | 0); // ?????��??? + ��????
    if (!I2C_ReadACK(bus_id)) ;//return false;

    I2C_SendByte(bus_id, reg_addr);  // ???????????
    if (!I2C_ReadACK(bus_id)) ;//return false;

    for (uint8_t i = 0; i < length; i++) {
        I2C_SendByte(bus_id, data[i]);  // ???????????
        if (!I2C_ReadACK(bus_id)) ;//return false;
    }

    I2C_Stop(bus_id);  // ????I2C???
    return true;
}


/*********************************************************************************
* function   :   I2C_Read    
* Description :  ???????I2C??????????
**********************************************************************************/
bool I2C_Read(uint8_t bus_id, uint8_t device_addr, uint8_t reg_addr, uint8_t *data, uint8_t length) {
    if (bus_id >= I2C_BUS_COUNT || data == NULL || length == 0) {
        return false; // ????????��??
    }

    I2C_Start(bus_id);
    //if (!I2C_ReadACK(bus_id)) return false; // ???ACK???

    I2C_SendByte(bus_id, (device_addr << 1) | 0);  // ?????��?????��????
    if (!I2C_ReadACK(bus_id)) ;//return false;

    I2C_SendByte(bus_id, reg_addr);  // ???????????
    if (!I2C_ReadACK(bus_id)) ;//return false;

    //I2C_Stop(bus_id);  // ?????????��?????????

    I2C_Start(bus_id);
    //if (!I2C_ReadACK(bus_id)) return false;

    I2C_SendByte(bus_id, (device_addr << 1) | 1);  // ?????��???????????
    if (!I2C_ReadACK(bus_id)) ;//return false;

  // ?��???????????????????
    for (uint8_t i = 0; i < length; i++) {
        data[i] = I2C_ReceiveByte(bus_id);  // ??????

        if (length == 1) {  
            // **?????????????????NACK**
					//printf("NACK\r\n");
            I2C_SendACK(bus_id, false);  // ????NACK
        } else if (i < length - 1) {
            // **????????????????????????????ACK**
            I2C_SendACK(bus_id, true);
        } else {
            // **????????????NACK**
            I2C_SendACK(bus_id, false);
        }
    }

    I2C_Stop(bus_id);  // ??I2C???
    return true;
}

